﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using System.IO;

namespace Intellisense
{
    public static class DisplayManager
    {
        public static bool IsProperty(string target, int currentPosition)
        {
            if (string.IsNullOrWhiteSpace(target))
                return false;

            if (IsTask(target, currentPosition))
                return false;

            Match startElementMatch = MSBuildMatch.FindLastMatch(target, Constants.StartElementPattern, currentPosition,false);
            if (startElementMatch != null)
            {
                bool result = true;
                Group closeGroup = startElementMatch.Groups[Constants.StartElementPatternCloseTagGroupName];
                if (closeGroup.Index < currentPosition && currentPosition < closeGroup.Index + closeGroup.Length)
                    result = false;
                if (result)
                {
                    Group taskGroup = startElementMatch.Groups[Constants.StartElementPatternTaskNameGroupName];
                    if (taskGroup.Index < currentPosition && currentPosition < taskGroup.Index + taskGroup.Length)
                        result = false;
                }
                if (result)
                {
                    Group propertyGroup = startElementMatch.Groups[Constants.StartElementPatternPropertiesTextGroupName];
                    if (!string.IsNullOrWhiteSpace(propertyGroup.Value))
                    {
                        MatchCollection propMatches = MSBuildMatch.GetMatches(propertyGroup.Value, Constants.PropertyPattern, 0);
                        foreach (Match propMatch in propMatches)
                        {
                            if (propertyGroup.Index + propMatch.Index < currentPosition && currentPosition < propertyGroup.Index + propMatch.Length + propMatch.Index)
                            {
                                result = false;
                                break;
                            }
                        }
                    }
                }
                return result;
            }
            return false;
        }

        public static bool IsTask(string target, int currentPosition)
        {
            if (string.IsNullOrWhiteSpace(target))
                return false;

            if (IsNotStartElement(target, currentPosition))
                return false;

            Match startElementMatch = MSBuildMatch.FindLastMatch(target, Constants.StartElementPattern, currentPosition,false);
            if (startElementMatch != null)
            {
                Group taskGroup = startElementMatch.Groups[Constants.StartElementPatternTaskNameGroupName];
                if (!taskGroup.Success)
                    return true;
                else
                {
                    if (currentPosition <= taskGroup.Index + taskGroup.Value.Length)
                        return true;
                }
            }
            else
            {
                Match startTagOnlyMatch = MSBuildMatch.FindLastMatch(target, Constants.StartElementTagPattern, currentPosition, true);
                if (startTagOnlyMatch != null)
                    return true;
            }
            return false;
        }

        public static bool IsDisplay(string target, int currentPosition)
        {
            if (string.IsNullOrWhiteSpace(target))
                return false;

            if (!MSBuildMatch.IsExist(target, Constants.XmlDeclarationPattern))
                return false;

            if (IsNotStartElement(target, currentPosition))
                return false;
            
            //StartElement
            Match startElementMatch = MSBuildMatch.FindLastMatch(target, Constants.StartElementPattern, currentPosition,false);
            if (startElementMatch != null)
            {
                Group closeGroup = startElementMatch.Groups[Constants.StartElementPatternCloseTagGroupName];
                if (IsBetween(closeGroup.Index, closeGroup.Index + closeGroup.Value.Length, currentPosition))
                    return false;

                Group propGroup = startElementMatch.Groups[Constants.StartElementPatternPropertiesTextGroupName];
                if (!string.IsNullOrWhiteSpace(propGroup.Value))
                {
                    Regex rg = new Regex(Constants.AttributesPattern, RegexOptions.Singleline);
                    MatchCollection matches = rg.Matches(propGroup.Value);
                    if (matches != null && matches.Count > 0)
                    {
                        foreach (Match match in matches)
                        {
                            int propStart = propGroup.Index + match.Index;
                            int propEnd = propStart + match.Value.Length;
                            if (IsBetween(propStart, propEnd, currentPosition))
                            {
                                string preText = target.Substring(currentPosition - 2, 2);
                                if (preText != "$(" && preText != "%(" && preText != "@(")
                                    return false;
                            }
                        }
                    }
                }

                Group taskGroup = startElementMatch.Groups[Constants.StartElementPatternTaskNameGroupName];
                if (IsBetween(taskGroup.Index, taskGroup.Index + taskGroup.Value.Length, currentPosition))
                    return false;

            }

            return true;
        }

        private static bool IsNotStartElement(string target, int currentPosition)
        {
            if (currentPosition == 0)
                return true;

            //xml declaration
            MatchCollection decMatches = MSBuildMatch.GetMatches(target, Constants.XmlDeclarationPattern, 0);
            if (decMatches != null && decMatches.Count > 0)
            {
                if (currentPosition <= decMatches[0].Index)
                    return true;
            }
            if (MSBuildMatch.IsSelectedBetweenLastMatch(target, Constants.XmlDeclarationPattern, currentPosition))
                return true;

            //comment
            if (MSBuildMatch.IsSelectedBetweenLastMatch(target, Constants.CommentPattern, currentPosition))
                return true;

            //CDATA
            if (MSBuildMatch.IsSelectedBetweenLastMatch(target, Constants.CDATAPattern, currentPosition))
                return true;

            //EndElement
            if (MSBuildMatch.IsSelectedBetweenLastMatch(target, string.Format(Constants.EndElementPattern, "\\w*"), currentPosition))
                return true;
            return false;
        }

        private static bool IsBetween(int start, int end, int current)
        {
            if (start < current && current < end)
                return true;
            return false;
        }
        
    }
}
